package com.imyours.webservice.service;

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.imyours.webservice.services.annotation.Service;
import com.opensymphony.xwork2.util.finder.ClassFinder;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterfaceDelegate;

public class ServiceManager {
	private Map<String, String> serviceMap = null;
	private static Logger logger = LoggerFactory.getLogger(ServiceManager.class);

	public ServiceManager() {
		serviceMap = new HashMap<String, String>();
		init();
	}

	private void init() {
		// serviceMap.put("test",
		// "com.imyours.webservice.services.TestService");
		// serviceMap.put("login", "com.imyours.webservice.services.Login");
		// serviceMap.put("logout", "com.imyours.webservice.services.Logout");

		try {
			ClassFinder classFinder = new ClassFinder(new ClassLoaderInterfaceDelegate(Thread.currentThread()
					.getContextClassLoader()));
			List<Class> clazz = classFinder.findAnnotatedClasses(Service.class);
			String serviceName = null;
			for (int i = 0; i < clazz.size(); i++) {
				serviceName = ((Service) clazz.get(i).getAnnotation(Service.class)).name();
				serviceMap.put(serviceName, clazz.get(i).getName());
			}
		} catch (Exception e) {
			logger.warn("服务配置装载失败");
		}
	}

	@SuppressWarnings("unchecked")
	public void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String serviceName = request.getParameter("service");
		// logger.info("service:".concat(serviceName));
		if (serviceName != null && serviceMap.get(serviceName) != null) {
			String serviceClassName = serviceMap.get(serviceName);
			logger.info("class:".concat("className=".concat(serviceClassName)));
			Class serviceClass = null;
			try {
				serviceClass = Class.forName(serviceClassName);
				logger.info("class:".concat(serviceClass.toString()));
			} catch (ClassNotFoundException e) {
				errorpage(request, response, "服务调用失败");
				return;
			}
			ContextService contextService = null;
			Context context = new Context();
			context.setSession(request.getSession());
			context.setParameter(getParameter(request));
			try {
				Constructor constructor = serviceClass.getConstructor(Context.class);
				contextService = (ContextService) constructor.newInstance(context);
			} catch (Exception e) {
				logger.warn("构造ContextService实例失败", e);
			}
			contextService.execute();
			Map result = resultDisposer(context);
			JSONObject jo = new JSONObject();
			try {
				jo.accumulateAll(result);
			} catch (Exception ex) {
				logger.warn("转换成JSON失败", ex);
			}
			response.setCharacterEncoding("utf-8");
			response.setContentType("text/plain");
			PrintWriter pw = new PrintWriter(new OutputStreamWriter(response.getOutputStream(),"utf-8"));
			pw.print(jo.toString());
			pw.flush();

		} else {
			errorpage(request, response, "未注册的服务");
		}

	}

	private void errorpage(HttpServletRequest request, HttpServletResponse response, String msg)
			throws ServletException, IOException {
		request.setAttribute("errorMsg", msg);
		request.getRequestDispatcher("error.jsp").forward(request, response);
	}

	@SuppressWarnings("unchecked")
	private Map resultDisposer(Context context) {
		Map result = new HashMap();
		if (context != null) {
			ExecuteStateEnum state = context.getState();
			if (state == ExecuteStateEnum.success) {
				result.put("data", context.getResult());
			}
			result.put("state", state.name());
			result.put("error", context.getErrors());

		} else {
			logger.warn("传入的context为空");
		}
		return result;
	}

	private Map<String, String> getParameter(HttpServletRequest request) {
		Map<String, String> parameters = new HashMap<String, String>();
		// Map m = request.getParameterMap();
		Enumeration em = request.getParameterNames();
		String key = null;
		String value = null;
		while (em.hasMoreElements()) {
			key = (String) em.nextElement();
			value = (String) request.getParameter(key);
			parameters.put(key, value);
		}
		return parameters;
	}
}
